//
//GameControl.cc
//
//Created on: Mar 6, 2012
// Author: Muhammad Zohaib Hassan
//    Student Number : 223994
//
// Description :  it has definitions of all the Functions of Class GameControl
// GameControl Class Controls most of the Functions required by the
// Specification and Operates on the Question Class
//
//

#include<iostream>
#include<limits>
#include<fstream>
#include<cstdlib>
#include<ctime>
#include <iterator>
#include"GameControl.hh"

Question GameControl ::Get_Question_From_Console()
{

    string new_Question_Description;
    string new_Option_A="";
    string new_Option_B="";
    string new_Option_C="";
    string new_Option_D="";

    Question Question_read;

    list<Question> ::iterator iterate;

    char new_Answer;
    int new_Difficulty_Level;

    cout<<"Enter Question Description :";
    getline(cin,new_Question_Description,'?');

    cin.ignore();

    cout<<"Enter Answer A :";
    getline(cin,new_Option_A);

    cout<<"Enter Answer B :";
    getline(cin,new_Option_B);

    cout<<"Enter Answer C :";
    getline(cin,new_Option_C);

    cout<<"Enter Answer D :";
    getline(cin,new_Option_D);

    cout<<"Enter Correct Answer :";
    cin>>new_Answer;

    while(new_Answer !='A' && new_Answer !='B' && new_Answer !='C' && new_Answer !='D' )
    {
        cout<<"Please Select Correct Answer between Options <A..D>";
        cin>>new_Answer;
    }


    cout<<"Enter Difficulty Level :";
    cin>>new_Difficulty_Level;

    while(new_Difficulty_Level < 0 || new_Difficulty_Level > 12)
    {
        cout<<"Please Enter Correct Difficulty Level"<<endl<<"Difficulty Level:";
        cin>>new_Difficulty_Level;
    }

  // Set Question Attributes

    Question_read.Set_Question_Description(new_Question_Description);
    Question_read.Set_Option_A(new_Option_A);
    Question_read.Set_Option_B(new_Option_B);
    Question_read.Set_Option_C(new_Option_C);
    Question_read.Set_Option_D(new_Option_D);
    Question_read.Set_Answer(new_Answer);
    Question_read.Set_Difficulty_Level(new_Difficulty_Level);

    return Question_read;
}


void GameControl:: Add_New_Question()
{
    Question new_Question;

    new_Question =Get_Question_From_Console();

    Questions.push_back(new_Question);

    cout<<"Successfully Added"<<endl;


    cout<<"Press Any Key to Return to the Menu";
    cin.ignore();
    cin.ignore(std::numeric_limits<streamsize>::max(),'\n');
}


void GameControl::Print_Game_Menu()
{

    cout<<"Select Menu Item : "<<endl<<endl;
    cout<<"[1]  Add A New Question"<<endl;
    cout<<"[2]  Search A Question"<<endl;
    cout<<"[3]  Select"<<endl;
    cout<<"[4]  Print"<<endl;
    cout<<"[5]  Generate a Question Set"<<endl;
    cout<<"[6]  Save Questions to a File"<<endl;
    cout<<"[7]  Print the Generated Question Set"<<endl;

    cout<<"Your Choice: ";

}

void GameControl:: submenu_FOR_search()
{
    cout<<endl<<"[A] Edit Questions"<<endl;
    cout<<"[B] Print Questions "<<endl;
    cout<<"[C] Return to Start Menu.."<<endl;
    cout<<"Your Choice :";
}

int GameControl ::Question_Number_Validity()
{
    int Question_Number_To_Edit;
    cin>>Question_Number_To_Edit;

    list<int> ::iterator iterate_int;
    int Question_Number_IS_VALID=0;

    while(Question_Number_IS_VALID==0)
    {
      //CHECK if user provided Correct Question Number to EDIT
        for(iterate_int=Question_Numbers.begin();iterate_int != Question_Numbers.end();iterate_int++)
        {
            if(Question_Number_To_Edit == *iterate_int){
                Question_Number_IS_VALID=1;
            }
        }
        if(Question_Number_IS_VALID==0)
        {
            cout<<"ERROR : Please Provide Correct Question Number"<<endl;
            cout<<"Enter A Question Number to Edit :";
            cin>>Question_Number_To_Edit;
        }

    }	// While

    return Question_Number_To_Edit;

}

int GameControl ::Find_Questions()
{

    string Word_To_Search="";
    string Question_Description="";

    int Found;

    cout<<"Please Enter a word to Search :";
    cin>>Search;

    list<Question>::iterator iterate;
    list<int>::iterator iterate_int;

    int LOOP_COUNT=0;
    size_t found;

    Question Question_Found;

    // Check if Questions LIST is empty



    for(iterate=Questions.begin();iterate!=Questions.end();iterate++)
    {
        LOOP_COUNT++;
        Question_Description = iterate ->Get_Question_Description();
        found = Question_Description.find(Search);

        if (found!=string::npos)
        {
            Found=1;
            Question_Numbers.push_back(LOOP_COUNT);
        }
    }

  // PRINT Question Numbers Found having Desired String
    if(Question_Numbers.size() == 0)
    {
        cout<<"NO Question Found with String \" " <<Search<<"\""<<endl;
        Found=0;
        return Found;
    }

    cout<<"Questions containing the String \"" <<Search<<"\"  are :";
    for(iterate_int=Question_Numbers.begin();iterate_int!=Question_Numbers.end();iterate_int++)
    {
        cout<< *iterate_int<<"  ";
    }
    return Found;
}

// Prints user Requested Question After Searching Questions having a particular String

void Print_Question(list<Question>::iterator iterate)
{

    cout<<iterate->Get_Question_Description() <<'?'<<endl;
    cout<<iterate->Get_Option_A()<<endl;
    cout<<iterate->Get_Option_B()<<endl;
    cout<<iterate->Get_Option_C()<<endl;
    cout<<iterate->Get_Option_D()<<endl;
    cout<<iterate->Get_Answer()<<endl;
    cout<<iterate->Get_Difficulty_Level()<<endl;

    cin.ignore();

}

void GameControl::Search_Questions()
{
    Question Edited_Question;

    list<Question>::iterator iterate;
    list<int>::iterator iterate_int;

    char user_selects;

    int Question_Number_To_Edit=0;
    int Found_FLAG=0;
    int move=0;

    unsigned int Total_Questions=0;

    Total_Questions = Questions.size();
    if(Total_Questions == 0)
    {
        cout<<"Question LIST is EMPTY , Please Add some Questions First"<<endl;
        return;
    }

    while(Found_FLAG==0){
        Found_FLAG=Find_Questions();
    }
  // print sub Menu
    while(1)
    {
        submenu_FOR_search();

        cin>>user_selects;

      // Check if USER choice is valid
        while(user_selects !='A' && user_selects !='B' && user_selects !='C' )
        {
            cout<<"ERROR : Please selects correct Menu Option"<<endl;
            cout<<"Your Choice: ";
            cin>>user_selects;
        }


        switch(user_selects)
        {
            case 'A':
            {
                cout<<"Enter A Question Number to Edit :";
                Question_Number_To_Edit=Question_Number_Validity();

                cout<<"Editing Question # "<<Question_Number_To_Edit<<endl;

                iterate=Questions.begin();

                move= Question_Number_To_Edit -1;
                advance(iterate,move);
                Print_Question(iterate);

                Edited_Question =Get_Question_From_Console();		// Get EDITED Question from user

                if(Edited_Question.Get_Difficulty_Level() == 0)
                return;

                *iterate = Edited_Question;

                cout<<"Question EDITED Successfully"<<endl;
                break;
            }
            case'B':{
                cout<<"Enter A Question Number to Print :";
                Question_Number_To_Edit=Question_Number_Validity();

                iterate=Questions.begin();

                move= Question_Number_To_Edit -1;
                advance(iterate,move);
                Print_Question(iterate);
                break;
            }
            case'C':{
                return;
                break;
            }
        }

        cout<<"Questions containing the String \"" <<Search<<"\"  are :";
        for(iterate_int=Question_Numbers.begin();iterate_int!=Question_Numbers.end();iterate_int++){
            cout<< *iterate_int<<"  ";
        }
    }

}


void GameControl ::Save_Questions_To_File(char* FileName)

{

    ofstream File_Stream;
    list<Question>::iterator iterate;
    File_Stream.open(FileName);
    if(File_Stream.is_open())
    {
            // File_Stream << "Questions Repository!!"<<endl;
        for(iterate=Questions.begin();iterate!=Questions.end();iterate++)
        {
            File_Stream << iterate ->Get_Question_Description()<<endl;
            File_Stream << iterate->Get_Option_A() << endl;
            File_Stream << iterate ->Get_Option_B() << endl;
            File_Stream << iterate->Get_Option_C() << endl;
            File_Stream << iterate ->Get_Option_D() << endl;
            File_Stream << iterate->Get_Answer() << endl;
            File_Stream<< iterate -> Get_Difficulty_Level()<<endl;
        }

        cout<<"Successfully Saved to File"<<endl;
        File_Stream.close();
        cout<<"Press Any Key to Return to the Menu";
        cin.ignore(std::numeric_limits<streamsize>::max(),'\n');
    }

}


void GameControl::Read_Questions(char* FileName)
{

    string Question_Description="";
    string Option_A="";
    string Option_B="";
    string Option_C="";
    string Option_D="";

    char Answer;
    int Difficulty_Level=0;

    Question New_Question;

    ifstream File_Stream;
    list<Question>::iterator iterate;
    File_Stream.open(FileName);


  if(File_Stream.is_open())
    {
      while(getline(File_Stream,Question_Description))
	{

	  //getline(File_Stream,Question_Description);
	  New_Question.Set_Question_Description(Question_Description);

	  getline(File_Stream,Option_A);
	  New_Question.Set_Option_A(Option_A);

	  getline(File_Stream,Option_B);
	  New_Question.Set_Option_B(Option_B);

	  getline(File_Stream,Option_C);
	  New_Question.Set_Option_C(Option_C);

	  getline(File_Stream,Option_D);
	  New_Question.Set_Option_D(Option_D);

	  File_Stream>>Answer;
	  New_Question.Set_Answer(Answer);
	  //	File_Stream.ignore();

	  File_Stream>>Difficulty_Level;
	  New_Question.Set_Difficulty_Level(Difficulty_Level);

	  File_Stream.ignore();

	  Questions.push_back(New_Question);

	}

    }
}


void GameControl ::Print()

{

  while(1)
    {
      Submenu_FOR_Print();

      char user_Option;
      cout<<"Your Choice:";
      cin>>user_Option;

      while(user_Option !='A' && user_Option !='B' && user_Option !='C' && user_Option !='D' )
	{
	  cout<<"Please chose correct Option between <A..D>"<<endl;
	  cout<<"Your Choice:";
	  cin>>user_Option;
	}

      switch(user_Option)
	{

	case	'A':
	  Print_All_Questions();
	  break;
	case 'B':
	  Print_A_Question();
	  break;
	case 'C':
	  Print_by_Difficulty_LEVEL();
	  break;
	  // ************** SOLVE THIS Latter
	case 'D':
	  return;
	  break;

	}

    }

}

// Definition of Submenu_FOR_Print() method of GameControl Class
void GameControl ::  Submenu_FOR_Print()
{
  cout<<" [A] PRINT ALL QUESTIONS"<<endl;
  cout<<" [B] PRINT A QUESTION BY NUMBER"<<endl;
  cout<<" [C] PRINT QUESTIONS OF A PARTICULAR DIFFICULTY LEVEL"<<endl;
  cout<<" [D] RETURN TO START MENU ..."<<endl;
}

// Definition of Print_All_Questions() method of GameControl Class
void GameControl ::Print_All_Questions()
{
  int Q_Number=0;
  list<Question>::iterator iterate;
  for(iterate=Questions.begin();iterate!=Questions.end();iterate++)
    {
      Q_Number++;
      cout<< "Question # " <<Q_Number<<":"<<iterate ->Get_Question_Description()<<'?'<<endl;
      cout<< "Option A :" <<iterate ->Get_Option_A()<<endl;
      cout<< "Option B :" <<iterate ->Get_Option_B()<<endl;
      cout<< "Option C :"<<iterate ->Get_Option_C()<<endl;
      cout<< "Option D :"<<iterate ->Get_Option_D()<<endl;
      cout<< "Answer :" <<iterate ->Get_Answer()<<endl;
      cout<< "Difficulty Level: "<<iterate ->Get_Difficulty_Level()<<endl;
    }

}

// Definition of Print_A_Question() method of GameControl Class
void GameControl:: Print_A_Question()
{

  list<Question>::iterator iterate;

  unsigned int Total_Questions;
  unsigned int user_selects=0;
  unsigned int LOOP_COUNT=0;

  const unsigned int ZERO=0;

  Total_Questions=Questions.size();

  // Check if LIST is EMPTY
  if(Total_Questions==ZERO)
    {
      cout<<"There are No Questions in the Question Repository"<<endl;
      cout<<"Please Add Some Questions First"<<endl;
      return;
    }

  // Ask for Question Number to Print
  cout<<"Enter A Question Number [ 1-"<<Total_Questions<<"] :";
  cin>>user_selects;

  // Check if Question Number is valid
  while(user_selects < 1 || user_selects > Total_Questions)
    {
      cout<<"ERROR: Question Number should be from 1 -"<<Total_Questions<<endl;
      cout<<"Enter A Question Number [ 1-"<<Total_Questions<<"] :";
      cin>>user_selects;
    }

  // Get the Question from LIST to Print
  for(iterate=Questions.begin();iterate!=Questions.end();iterate++)
    {
      LOOP_COUNT++;
      if(user_selects == LOOP_COUNT)
	{
	  cout<< "Question #"<<user_selects<<":"<<iterate ->Get_Question_Description()<<'?'<<endl;
	  cout<< "Option A :" <<iterate ->Get_Option_A()<<endl;
	  cout<< "Option B :" <<iterate ->Get_Option_B()<<endl;
	  cout<< "Option C :"<<iterate ->Get_Option_C()<<endl;
	  cout<< "Option D :"<<iterate ->Get_Option_D()<<endl;
	  cout<< "Answer :" <<iterate ->Get_Answer()<<endl;
	  cout<< "Difficulty Level: "<<iterate ->Get_Difficulty_Level()<<endl;
	}
    }

}

// definition of  Print_by_Difficulty_LEVEL() Method of Class GameContrl
void GameControl ::Print_by_Difficulty_LEVEL()
{

  list<Question>::iterator iterate;		// LIST iterator
  int user_selects=0;
  int recieved_Difficulty_LEVEL=0;

  int Total_Questions;
  const int ZERO = 0;

  Total_Questions=Questions.size();

  // Check if the Questions LIST is EMPTY
  if(Total_Questions==ZERO)
    {
      cout<<"There are No Questions in the Question Repository"<<endl;
      cout<<"Please Add Some Questions First"<<endl;
      return;
    }

  // Ask for Valid Difficulty Level
  cout<<"PLease Enter the Difficulty Level [1-12] :";
  cin>>user_selects;

  // Check if provided Difficulty LEVEL is valid
  while(user_selects < 1 || user_selects > 12)
    {
      cout<<"Difficulty Level Provided is not VALID."<<endl;
      cout<<"Enter A valid Difficulty LEVEL [ 1-12] :";
      cin>>user_selects;
    }

  // PRINT Questions of The provided Difficulty LEVEL
  for(iterate=Questions.begin();iterate!=Questions.end();iterate++)
    {

      recieved_Difficulty_LEVEL = iterate ->Get_Difficulty_Level();
      if(recieved_Difficulty_LEVEL == user_selects)
	{
	  cout<< "Question #"<<user_selects<<":"<<iterate ->Get_Question_Description()<<'?'<<endl;
	  cout<< "Option A :" <<iterate ->Get_Option_A()<<endl;
	  cout<< "Option B :" <<iterate ->Get_Option_B()<<endl;
	  cout<< "Option C :"<<iterate ->Get_Option_C()<<endl;
	  cout<< "Option D :"<<iterate ->Get_Option_D()<<endl;
	  cout<< "Answer :" <<iterate ->Get_Answer()<<endl;
	  cout<< "Difficulty Level: "<<iterate ->Get_Difficulty_Level()<<endl;
	}
    }
}


void GameControl ::Select(char* FileName)

{
  const unsigned int ZERO =0;

  unsigned int user_selects=0;
  unsigned int Total_Questions = Questions.size();
  unsigned int LOOP_COUNT=0;

  char user_selects_SUBMENU;

  list<Question> ::iterator iterate;

  // Check if Question LIST is Empty
  if(Total_Questions==ZERO)
    {
      cout<<"There are No Questions in the Question Repository"<<endl;
      cout<<"Please Add Some Questions First"<<endl;
      return;
    }

  // Ask for Question Number to Select
  cout<<"Select Question Number [ 1-"<<Total_Questions<<"] :";
  cin>>user_selects;

  while(user_selects < 1 || user_selects > Total_Questions)
    {
      cout<<"ERROR: Question Number should be from 1 -"<<Total_Questions<<endl;
      cout<<"Enter A Question Number [ 1-"<<Total_Questions<<"] :";
      cin>>user_selects;
    }

  // PRINT Question
  for(iterate=Questions.begin();iterate!=Questions.end();iterate++)
    {
      LOOP_COUNT++;
      if(user_selects == LOOP_COUNT)
	{
	  cout<< "Question #"<<user_selects<<":"<<iterate ->Get_Question_Description()<<'?'<<endl;
	  cout<< "Option A :" <<iterate ->Get_Option_A()<<endl;
	  cout<< "Option B :" <<iterate ->Get_Option_B()<<endl;
	  cout<< "Option C :"<<iterate ->Get_Option_C()<<endl;
	  cout<< "Option D :"<<iterate ->Get_Option_D()<<endl;
	  cout<< "Answer :" <<iterate ->Get_Answer()<<endl;
	  cout<< "Difficulty Level: "<<iterate ->Get_Difficulty_Level()<<endl;
	}
    }

  while(1)
    {
      Submenu_FOR_Select();

      cout<<"Your Choice :";
      cin>>user_selects_SUBMENU;
      cin.ignore();

      switch(user_selects_SUBMENU)
	{
	case	'A':
	  Edit_Selected_Question(user_selects);
	  break;

	case 'B':
	  Remove_Selected_Question(user_selects);
	  break;
	  // SAVE Question To File :: Confusion  (Question List is saved again in Text File?)
	case 'C':
	  Save_Questions_To_File(FileName);
	  break;
	  // Return to Main Menu
	case 'D':
	  return;
	  break;

	}
    }



}

// Sub Menu for Select Function
void GameControl :: Submenu_FOR_Select()
{
  cout<<"[A] Edit Question"<<endl;
  cout<<"[B] Remove Question"<<endl;
  cout<<"[C] Save Question to FIle"<<endl;
  cout<<"[D] Return to Start Menu"<<endl;
}

void GameControl ::Edit_Selected_Question(unsigned int Question_Number)

{

  unsigned int LOOP_COUNT=0;

  Question Edited_Question;
  list<Question> ::iterator iterate;

  Edited_Question = Get_Question_From_Console();

  for(iterate=Questions.begin();iterate!=Questions.end();iterate++)
    {
      LOOP_COUNT++;
      if(Question_Number == LOOP_COUNT)
	{
	  iterate ->Set_Question_Description(Edited_Question.Get_Question_Description());
	  iterate ->Set_Option_A(Edited_Question.Get_Option_A());
	  iterate ->Set_Option_B(Edited_Question.Get_Option_B());
	  iterate ->Set_Option_C(Edited_Question.Get_Option_C());
	  iterate ->Set_Option_D(Edited_Question.Get_Option_D());

	  iterate ->Set_Answer(Edited_Question.Get_Answer());
	  iterate ->Set_Difficulty_Level(Edited_Question.Get_Difficulty_Level());
	}
    }

  cout<<"SuccessFully Edited"<<endl;
}

void GameControl::  Remove_Selected_Question(unsigned int Question_Number)

{
  Question Edited_Question;
  list<Question> ::iterator iterate;
  list<Question> :: iterator new_iterator;

  iterate = Questions.begin();

  unsigned int move = Question_Number-1;
  advance (iterate,move);

  Questions.erase(iterate);

  cout<<"Successfully Removed"<<endl;
}

// Generate Question Set

void GameControl::Generate_Question_Set()

{

  list<Question> ::iterator iterate;
  Question List_candidate;

  unsigned int size=0;
  size= Questions.size();
  if(size==0)
    {
      cout<<"Question LIST is empty , please Add some Questions First"<<endl;
      return;
    }


  for(int i=1;i<13;i++)
    {
      List_candidate=Filter_Question(i);
      Generated_Question.push_back(List_candidate);
    }

  cout<<"Question Set SuccessFully Generated"<<endl;
  cout<<"Press Any Key to Return to the Menu";
  cin.ignore(std::numeric_limits<streamsize>::max(),'\n');

}


// Filter Question of a Given Difficulty LEVEL
Question GameControl ::Filter_Question(int LEVEL)

{
  list<Question> Questions_of_LEVEL;

  list<Question> ::iterator iterate;
  Question Filtered_Question;

  int lookLIST=0;
  int Diff_LEVEL=0;
  unsigned int size=0;

  int randomNumber;
  int upperBound;

  bool enough_Questions=0;		// FLAG to check if there is atleast 1 question across given Difficulty LEVEL

  for(iterate=Questions.begin();iterate!=Questions.end();iterate++)
    {
      Diff_LEVEL=iterate ->Get_Difficulty_Level();
      if(Diff_LEVEL == LEVEL)

	{
	  enough_Questions=1;
	  Filtered_Question.Set_Question_Description(iterate->Get_Question_Description());
	  Filtered_Question.Set_Option_A(iterate ->Get_Option_A());
	  Filtered_Question.Set_Option_B(iterate->Get_Option_B());
	  Filtered_Question.Set_Option_C(iterate ->Get_Option_C());
	  Filtered_Question.Set_Option_D(iterate ->Get_Option_D());

	  Filtered_Question.Set_Answer(iterate ->Get_Answer());
	  Filtered_Question.Set_Difficulty_Level(iterate ->Get_Difficulty_Level());

	  Questions_of_LEVEL.push_back(Filtered_Question);
	}

    }

  if(enough_Questions == 0)
    {
      cout<<"Please Add Sufficient Questions first.There is no Question available for Difficulty Level ="<<endl<<LEVEL;
      Filtered_Question.Set_Difficulty_Level(0);
      return Filtered_Question;
    }

  size=static_cast <int> (Questions_of_LEVEL.size());
  upperBound=size;
  srand(static_cast <int>(time(NULL)));  // Initializes the random number generator.
  randomNumber =static_cast <int>(static_cast <int>(rand())%upperBound) + 1; // Formula to get the random

  // Pick a Random Question

  for(iterate=Questions_of_LEVEL.begin();iterate!=Questions_of_LEVEL.end();iterate++)
    {
      lookLIST++;
      if(randomNumber == lookLIST)
	{
	  Filtered_Question=*iterate;
	  return Filtered_Question;
	}
    }

  return Filtered_Question;
}


void GameControl::Print_Generated_Question_Set()
{
  list<Question>::iterator iterate;
  unsigned int SIZE=0;
  int Q_Number=0;
  SIZE=Generated_Question.size();
  if(SIZE == 0)
    {
      cout<<"ERROR :Please Generate Question SET first"<<endl;
      cout<<"Press Any Key to Return to the Menu";
      cin.ignore(std::numeric_limits<streamsize>::max(),'\n');
      return;
    }

  for(iterate=Generated_Question.begin();iterate!=Generated_Question.end();iterate++)
    {
      Q_Number++;
      cout<< "Question #"<<Q_Number<<":"<<iterate ->Get_Question_Description()<<'?'<<endl;
      cout<< "Option A :" <<iterate ->Get_Option_A()<<endl;
      cout<< "Option B :" <<iterate ->Get_Option_B()<<endl;
      cout<< "Option C :"<<iterate ->Get_Option_C()<<endl;
      cout<< "Option D :"<<iterate ->Get_Option_D()<<endl;
      cout<< "Answer :" <<iterate ->Get_Answer()<<endl;
      cout<< "Difficulty Level: "<<iterate ->Get_Difficulty_Level()<<endl;


    }
}

int GameControl ::List_Size()

{
  int Size=0;
  Size=Questions.size();
  return Size;
}





